#include "SequencedChannel.h"
#include <chrono>
#include <cstring>
#include "NetConstants.h"
#include "NetPacketPool.h"
#include "NetUtils.h"
#include "NetPeer.h"
#include "NetManager.h"
#include "spdlog/spdlog.h"
#include "NetDebug.h"

namespace LiteNetLib
{
    SequencedChannel::SequencedChannel(NetPeer *netPeer, bool reliable, uint8_t channelId) : 
        BaseChannel(netPeer), 
        m_remoteSequence(0),
        m_reliable(reliable), 
        m_lastPacket(nullptr),
        m_ackPacket(nullptr),
        m_channelId(channelId)
    {
        if(m_reliable == true)
        {
            m_ackPacket = new NetPacket(PacketProperty::Ack, 0);
            // 清空数据，以防冲突
            memset(m_ackPacket->getRawData() + 1, 0, m_ackPacket->getPacketSize() - 1);
            m_ackPacket->setChannelId(m_channelId);
        }
    }


    SequencedChannel::~SequencedChannel()
    {
        if(m_lastPacket != nullptr)
        {
            delete m_lastPacket;
        }
        if(m_ackPacket != nullptr)
        {
            delete m_ackPacket;
        }
    }


    void SequencedChannel::clear()
    {
        BaseChannel::clear();
        std::lock_guard<std::mutex> lk(m_lastPacketMutex);
        
        if(m_lastPacket != nullptr)
        {
            NetPacketPool::GetInstance().recycleOrDelete(m_lastPacket);
            m_lastPacket = nullptr;
        }
    }


    bool SequencedChannel::sendNextPackets()
    {
        std::lock_guard<std::mutex> lk(m_lastPacketMutex);

        // 队列中数据包的发送
        if(m_reliable && m_outgoingQueue.size() == 0)
        {
            int64_t currentTime = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now().time_since_epoch()).count();
            int64_t packetHoldTime = currentTime - m_lastPacketSendTime;
            if(packetHoldTime >= NetConstants::PacketResendDelay)
            {
                if(m_lastPacket != nullptr)
                {
                    m_lastPacketSendTime = currentTime;
                    m_netPeer->sendUserPacket(m_lastPacket);
                }
            }
        }
        else
        {
            NetPacket *netPacket = nullptr;
            while(m_outgoingQueue.try_pop(netPacket))
            {
                m_localSequence = (m_localSequence + 1) % NetConstants::MaxSequence;
                netPacket->setSequence((uint16_t)m_localSequence);
                netPacket->setChannelId(m_channelId);
                m_netPeer->sendUserPacket(netPacket);

                NetDebug::Info("SequencedChannel send user packet");
                
                // 最后一个包需要记录时间，用于重发处理
                if(m_reliable && m_outgoingQueue.size() == 0)
                {
                    m_lastPacketSendTime = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now().time_since_epoch()).count();
                    // 若最后一个包有数据，记得回收，不然会内存泄漏
                    if(m_lastPacket != nullptr)
                    {
                        NetPacketPool::GetInstance().recycleOrDelete(m_lastPacket);
                    }
                    m_lastPacket = netPacket;
                }
                else
                {
                    NetPacketPool::GetInstance().recycleOrDelete(netPacket);
                }
            }
        }

        // ack 包的发送
        if(m_reliable && m_mustSendAck)
        {
            m_mustSendAck = false;
            m_ackPacket->setSequence(m_remoteSequence);
            m_netPeer->sendUserPacket(m_ackPacket);
        }
        return m_lastPacket != nullptr;
    }

    bool SequencedChannel::processData(const char* dataBuff, uint32_t dataSize)
    {
        if (NetPacket::IsFragmented(dataBuff))
        {
            return false;
        }
        if(NetPacket::GetProperty(dataBuff) == PacketProperty::Ack)
        {
            std::lock_guard<std::mutex> lk(m_lastPacketMutex);

            if(m_reliable && m_lastPacket != nullptr && NetPacket::GetSequence(dataBuff) == m_lastPacket->getSequence())
            {
                m_lastPacket = nullptr;
            }
            return false;
        }
        int32_t relative = NetUtils::RelativeSequenceNumber(NetPacket::GetSequence(dataBuff), m_remoteSequence);
        bool packetProcessed = false;
        if (NetPacket::GetSequence(dataBuff) < NetConstants::MaxSequence && relative > 0)
        {
            NetPacket *netPacket = NetPacketPool::GetInstance().getPacket(dataSize);
            memcpy(netPacket->getRawData(), dataBuff, dataSize);

            m_remoteSequence = netPacket->getSequence();
            // handle packet
            m_netPeer->getNetManager()->createReceiveEvent(netPacket, (m_reliable ? DeliveryMethod::ReliableSequenced : DeliveryMethod::Sequenced), NetConstants::ChanneledHeaderSize, m_netPeer->shared_from_this());

            packetProcessed = true;
        }
        
        // 若是可靠通道，就需要发送ack包，而发送ack包则需要将自身添加进NetPeer的发送队列中
        if (m_reliable)
        {
            m_mustSendAck = true;
            addToPeerSendQueue();
        }
        return packetProcessed;
    }
}